package com.he.heblog.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.he.heblog.dto.ArticleDto;
import com.he.heblog.dto.NotificationDto;
import com.he.heblog.dto.UserDto;
import com.he.heblog.entity.*;
import com.he.heblog.entity.validInterface.addValid;
import com.he.heblog.entity.validInterface.sendMsg;
import com.he.heblog.service.*;
import org.apache.ibatis.annotations.Lang;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private ArticleService articleService;
    @Autowired
    private FanService fanService;
    @Autowired
    NotificationService notificationService;

    /*注册用户时，*/
    @RequestMapping("/register")
    @ResponseBody
    public String registerUser(@Validated(addValid.class) UserDto user) {
//比较验证码是否一致
        String code = user.getCode();
        String validCode = (String) redisTemplate.opsForValue().get(user.getEmail());
        if (code.equals(validCode)) {
//        查询是否存在该邮箱用户
            LambdaQueryWrapper<User> Wrapper = new LambdaQueryWrapper<>();
            Wrapper.eq(user.getEmail() != null, User::getEmail, user.getEmail());
            User one = userService.getOne(Wrapper);
            if (one != null)
                return "当前邮箱已经存在用户，请更换邮箱或找回账号";
            //注册用户
            //进行密码加密
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            String encode = passwordEncoder.encode(user.getPassword());
            String password = "{bcrypt}" + encode;
            user.setPassword(password);
            userService.save(user);
            // 向用户角色表中注册用户角色信息
            UserRole userRole = new UserRole();
            userRole.setUserID(user.getId());
            userRole.setRoleID(1);
            userRoleService.save(userRole);
            return "success";
        } else return "验证码不一致，请重新获取";
    }

    @GetMapping
    public String getUser() {
        return "front/user/userIndex";
    }

    //删除用户
    @DeleteMapping("/delete/{id}")
    public String deleteUser(@PathVariable Integer id) {
//删除用户信息
        userService.removeById(id);
// 删除用户角色表中的信息
        LambdaQueryWrapper<UserRole> Wrapper = new LambdaQueryWrapper<>();
        Wrapper.eq(UserRole::getUserID, id);
        userRoleService.remove(Wrapper);
        return null;
    }

    //编辑用户
    @ResponseBody
    @PostMapping("/updatePwd")
    public String updatePwd(@Validated(sendMsg.class) UserDto userDto) {
//比对验证码是否一致
        String code = userDto.getCode();
        String validCode = (String) redisTemplate.opsForValue().get(userDto.getEmail());
//验证码一致则进行加密，保存到数据库
        if (code.equals(validCode)) {
            //进行密码加密
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            String encode = passwordEncoder.encode(userDto.getPassword());
            String password = "{bcrypt}" + encode;
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            UserDto principal = (UserDto) authentication.getPrincipal();
            Integer id = principal.getId();
            User user = new User();
            user.setId(id);
            user.setPassword(password);
            userService.updateById(user);
            return "success";
        } else
            return "验证码不一致，请重新获取";
    }

    //验证旧邮箱
    @ResponseBody
    @PostMapping("/checkEmail")
    public String chenkEmail(@Validated(sendMsg.class) UserDto userDto) {
//比对验证码是否一致
        String code = userDto.getCode();
        String validCode = (String) redisTemplate.opsForValue().get(userDto.getEmail());
//验证码一致则进行加密，保存到数据库
        if (code.equals(validCode)) {
            return "success";
        } else
            return "验证码不一致，请重新获取";
    }

    @ResponseBody
    @PostMapping("/updateEmail")
    public String updateEmail(@Validated(sendMsg.class) UserDto userDto) {
//比对验证码是否一致
        String code = userDto.getCode();
        String validCode = (String) redisTemplate.opsForValue().get(userDto.getEmail());
//验证码一致则进行加密，保存到数据库
        if (code.equals(validCode)) {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            UserDto principal = (UserDto) authentication.getPrincipal();
            Integer id = principal.getId();
            User user = new User();
            user.setId(id);
            user.setEmail(userDto.getEmail());
//            更新会话中的用户信息
            principal.setEmail(userDto.getEmail());
            userService.updateById(user);
            return "success";
        } else
            return "验证码不一致，请重新获取";
    }

    @PostMapping("/edit")
    public String updateUser(UserDto userDto) {
//获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
//更改用户的性别和自我介绍

        return "front/user/setUp";
    }


    //    跳转到用户编辑页
//    返回当前用户的详细信息
    @GetMapping("/edit")
    public String toEdit(Model model) {
//获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        model.addAttribute("condition", "all");
        model.addAttribute("user", principal);
        return "front/user/setUp";
    }

    @GetMapping("/updatePassword")
    public String toEditPassword(Model model) {
//获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        model.addAttribute("condition", "updatePWD");
        model.addAttribute("user", principal);
        return "front/user/setUp";
    }

    @GetMapping("/checkEmail")
    public String toEditEmail(Model model) {
//获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        model.addAttribute("condition", "checkEmail");
        model.addAttribute("user", principal);
        return "front/user/setUp";
    }

    @GetMapping("/updateEmail")
    public String toUpdateEmail(Model model) {
//获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        model.addAttribute("condition", "updateEmail");
        model.addAttribute("user", principal);
        return "front/user/setUp";
    }

// 根据用户名查询用户详情
// 返回该用户接受的通知，默认返回点赞通知
// 根据路径参数判断要查询什么
    @GetMapping("/detail/{condition}")
    public String userDetail(Model model, @PathVariable String condition) {
//        根据条件判断需要查询的数据是什么
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        int id = principal.getId();
        if ("article".equals(condition)) {
//            查询登录用户的文章信息
            ArticleDto articleDto = new ArticleDto();
            articleDto.setUserid(id);
            Page<ArticleDto> articleCondition = articleService.getArticleCondition(1, articleDto);
            model.addAttribute("ArticleList", articleCondition);
            model.addAttribute("condition", "article");
        }
        if ("fan".equals(condition)) {
//            查询登录用户的粉丝
            Page<User> userListPageById = userService.getUserListPageById(id, 1);

            model.addAttribute("ArticleList", userListPageById);
            model.addAttribute("condition", "fan");
        }
        if ("follow".equals(condition)) {
//            查询登录用户的关注
            Page<User> followPageById = userService.getFollowPageById(id, 1);
            model.addAttribute("ArticleList", followPageById);
            model.addAttribute("condition", "follow");
        }
//        获取当前用户的获赞数，浏览量，文章数
//        根据用户ID查询文章表
        LambdaQueryWrapper<Article> articleWrapper = new LambdaQueryWrapper<>();
        articleWrapper.eq(Article::getUserid, id);
        List<Article> list = articleService.list(articleWrapper);
        int articleCount = list.size();
//查询当前用户接受到的通知
        Page<Notification> page= new Page<>(1, 5);
        LambdaQueryWrapper<Notification> QueryWrapper = new LambdaQueryWrapper<>();
        QueryWrapper.eq(Notification::getSubject,1);
        QueryWrapper.eq(Notification::getToId,id);
        Page<Notification> page1 = notificationService.page(page, QueryWrapper);
        Page<NotificationDto> notificationDtoPage = new Page<>();
        BeanUtils.copyProperties(page,notificationDtoPage,"records");
//        获取用户ID
        List<Notification> records = page1.getRecords();
//      为每一个通知绑定信息



//        根据文章ID查询总的文章获赞数以及浏览量
        Optional<Integer> supportCount = list.stream().map(x -> x.getSupportCount()).reduce((x, y) -> x + y);
        Optional<Integer> visitorCount = list.stream().map(x -> x.getVisitorVolume()).reduce((x, y) -> x + y);
        model.addAttribute("supportCount", supportCount.orElse(0));
        model.addAttribute("visitorCount", visitorCount.orElse(0));
        model.addAttribute("articleCount", articleCount);
        return "front/user/personal";
    }

    @GetMapping("/detail/{condition}/{page}")
    public String userDetail(Model model, @PathVariable Integer page, @PathVariable String condition) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        int id = principal.getId();
//        根据条件判断需要查询的数据是什么
        if ("article".equals(condition)) {
//            查询登录用户的文章信息
            ArticleDto articleDto = new ArticleDto();
            articleDto.setUserid(id);
            Page<ArticleDto> articleCondition = articleService.getArticleCondition(page, articleDto);
            model.addAttribute("ArticleList", articleCondition);
        }
        if ("fans".equals(condition)) {
            Page<User> userListPageById = userService.getUserListPageById(id, page);
            model.addAttribute("fanList", userListPageById);
        }
        if ("follow".equals(condition)) {
//            查询登录用户的关注用户列表
            LambdaQueryWrapper<Fan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Fan::getOtherID, id);
            model.addAttribute("condition", "follow");
        }
//        获取当前用户的获赞数，浏览量，文章数
//        根据用户ID查询文章表
        LambdaQueryWrapper<Article> articleWrapper = new LambdaQueryWrapper<>();
        articleWrapper.eq(Article::getUserid, id);
        List<Article> list = articleService.list(articleWrapper);
        int articleCount = list.size();
//        根据文章ID查询总的文章获赞数以及浏览量
        Optional<Integer> supportCount = list.stream().map(x -> x.getSupportCount()).reduce((x, y) -> x + y);
        Optional<Integer> visitorCount = list.stream().map(x -> x.getVisitorVolume()).reduce((x, y) -> x + y);
        model.addAttribute("supportCount", supportCount.orElse(0));
        model.addAttribute("visitorCount", visitorCount.orElse(0));
        model.addAttribute("articleCount", articleCount);
        return "front/user/personal";
    }

    //  根据ID查询个人主页 需要查询当前用户是否关注了该用户
    @GetMapping("/detailToOther/{condition}/{id}")
    public String userDetail(Model model, @PathVariable String condition, @PathVariable Integer id) {
//        根据条件判断需要查询的数据是什么
        if ("article".equals(condition)) {
//            查询登录用户的文章信息
            ArticleDto articleDto = new ArticleDto();
            articleDto.setUserid(id);
            Page<ArticleDto> articleCondition = articleService.getArticleCondition(1, articleDto);
            model.addAttribute("ArticleList", articleCondition);
            model.addAttribute("condition", "article");
        }
        if ("fan".equals(condition)) {
//            查询登录用户的粉丝
            Page<User> userListPageById = userService.getUserListPageById(id, 1);
            model.addAttribute("ArticleList", userListPageById);
            model.addAttribute("condition", "fan");
        }
        if ("follow".equals(condition)) {
//            查询登录用户的关注
            Page<User> followPageById = userService.getFollowPageById(id, 1);
            model.addAttribute("ArticleList", followPageById);
            model.addAttribute("condition", "follow");
        }
//        获取当前用户的获赞数，浏览量，文章数
//        根据用户ID查询文章表
        LambdaQueryWrapper<Article> articleWrapper = new LambdaQueryWrapper<>();
        articleWrapper.eq(Article::getUserid, id);
        List<Article> list = articleService.list(articleWrapper);
        int articleCount = list.size();
//根据id查询用户信息
        User byId = userService.getById(id);
//新建传输对象
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(byId, userDto);
//查询关注表，查询关键粉丝表
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        LambdaQueryWrapper<Fan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Fan::getUserID, principal.getId());
        queryWrapper.eq(Fan::getOtherID, id);
        Fan one = fanService.getOne(queryWrapper);
        if (one != null)
            userDto.setIsFollow(1);
        else
            userDto.setIsFollow(0);
//        根据文章ID查询总的文章获赞数以及浏览量
        Optional<Integer> supportCount = list.stream().map(x -> x.getSupportCount()).reduce((x, y) -> x + y);
        Optional<Integer> visitorCount = list.stream().map(x -> x.getVisitorVolume()).reduce((x, y) -> x + y);
        model.addAttribute("supportCount", supportCount.orElse(0));
        model.addAttribute("visitorCount", visitorCount.orElse(0));
        model.addAttribute("articleCount", articleCount);
        model.addAttribute("user", userDto);
        return "front/user/otherPersonal";
    }

    @GetMapping("/detailToOther/{condition}/{page}/{id}")
    public String userDetail(Model model, @PathVariable Integer page, @PathVariable String condition, @PathVariable Integer id) {
//        根据条件判断需要查询的数据是什么
        if ("article".equals(condition)) {
//            查询登录用户的文章信息
            ArticleDto articleDto = new ArticleDto();
            articleDto.setUserid(id);
            Page<ArticleDto> articleCondition = articleService.getArticleCondition(page, articleDto);
            model.addAttribute("ArticleList", articleCondition);
        }
        if ("fans".equals(condition)) {
            Page<User> userListPageById = userService.getUserListPageById(id, page);
            model.addAttribute("fanList", userListPageById);
        }
        if ("follow".equals(condition)) {
//            查询登录用户的关注用户列表
            LambdaQueryWrapper<Fan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Fan::getOtherID, id);
            model.addAttribute("condition", "follow");
        }
//        获取当前用户的获赞数，浏览量，文章数
//        根据用户ID查询文章表
        LambdaQueryWrapper<Article> articleWrapper = new LambdaQueryWrapper<>();
        articleWrapper.eq(Article::getUserid, id);
        List<Article> list = articleService.list(articleWrapper);
        int articleCount = list.size();
        //根据id查询用户信息
        User byId = userService.getById(id);
        //新建传输对象
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(byId, userDto);
//查询关注表，查询关键粉丝表
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        LambdaQueryWrapper<Fan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Fan::getUserID, principal.getId());
        queryWrapper.eq(Fan::getOtherID, id);
        Fan one = fanService.getOne(queryWrapper);
        if (one != null)
            userDto.setIsFollow(1);
        else
            userDto.setIsFollow(0);
//        根据文章ID查询总的文章获赞数以及浏览量
        Optional<Integer> supportCount = list.stream().map(x -> x.getSupportCount()).reduce((x, y) -> x + y);
        Optional<Integer> visitorCount = list.stream().map(x -> x.getVisitorVolume()).reduce((x, y) -> x + y);
        model.addAttribute("supportCount", supportCount.get());
        model.addAttribute("visitorCount", visitorCount.get());
        model.addAttribute("articleCount", articleCount);
        model.addAttribute("user", userDto);
        return "front/user/otherPersonal";
    }

    @RequestMapping("/index")
    public String toUserIndex(Model model) {
//  根据点赞数返回文章列表，不区分文章类型
        ArticleDto articleDto = new ArticleDto();
        articleDto.setSupportCount(1);
        Page<ArticleDto> articleListOrder = articleService.getArticleListOrder(1, 4, null, articleDto);
//     根据浏览量返回文章列表，只需传输文章标题和ID
        LambdaQueryWrapper<Article> articleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        articleLambdaQueryWrapper.orderByDesc(Article::getVisitorVolume);
        articleLambdaQueryWrapper.last("limit 10");
        articleLambdaQueryWrapper.select(Article::getId, Article::getTitle);
        List<Article> list = articleService.list(articleLambdaQueryWrapper);
// 根据发布时间返回文章列表，只需传输文章标题和ID以及是否原创
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(Article::getPublicTime);
        wrapper.last("limit 10");
        wrapper.select(Article::getId, Article::getTitle, Article::getIsOrigin);
        List<Article> list2 = articleService.list(wrapper);
//  加入model中传输
        model.addAttribute("volumeList", list);
        model.addAttribute("timeList", list2);
        model.addAttribute("ArticleList", articleListOrder);
        return "front/user/userIndex";
    }

    @RequestMapping("/index/{page}")
    public String toUserIndex(Model model, @PathVariable Integer page) {
//  根据点赞数返回文章列表，不区分文章类型
        ArticleDto articleDto = new ArticleDto();
        articleDto.setSupportCount(1);
        Page<ArticleDto> articleListOrder = articleService.getArticleListOrder(page, 4, null, articleDto);
//     根据浏览量返回文章列表，只需传输文章标题和ID
        LambdaQueryWrapper<Article> articleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        articleLambdaQueryWrapper.orderByDesc(Article::getVisitorVolume);
        articleLambdaQueryWrapper.last("limit 10");
        articleLambdaQueryWrapper.select(Article::getId, Article::getTitle);
        List<Article> list = articleService.list(articleLambdaQueryWrapper);
// 根据发布时间返回文章列表，只需传输文章标题和ID以及是否原创
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(Article::getPublicTime);
        wrapper.last("limit 10");
        wrapper.select(Article::getId, Article::getTitle, Article::getIsOrigin);
        List<Article> list2 = articleService.list(wrapper);
//  加入model中传输
        model.addAttribute("volumeList", list);
        model.addAttribute("timeList", list2);
        model.addAttribute("ArticleList", articleListOrder);
        return "front/user/userIndex";
    }

    //跳转到私信界面，需要传送被私信用户的ID
    @GetMapping("/toChat/{id}")
    public String toChat(Model model, @PathVariable Integer id) {
//        根据用户ID查询用户信息
        User user = userService.getById(id);
        model.addAttribute("user", user);
        return "front/user/chat";
    }

    //发送私信
    @ResponseBody
    @PostMapping("/submitChat/{id}")
    public String submitChat(Model model, @PathVariable Integer id, Notification notification) {
//        获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        Integer id1 = principal.getId();
//
        notification.setFromId(id1);
        notification.setToId(id);
        notification.setSubject(4);
//保存信息到通知表中
        notificationService.save(notification);
        return "success";
    }

    //    点击关注，成为某个人的粉丝
    @GetMapping("/beFans/{id}")
    public String beFans(@PathVariable Integer id) {
//         新增一天记录到粉丝表中
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        Fan fan = new Fan();
        fan.setUserID(principal.getId());
        fan.setOtherID(id);
        boolean save = fanService.save(fan);
        return "redirect:/user/detailToOther/article/"+id;
    }
    @GetMapping("/cancelFan/{id}")
   public String cancelFans(@PathVariable Integer id)
    {
//        删除粉丝表的记录
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDto principal = (UserDto) authentication.getPrincipal();
        LambdaQueryWrapper<Fan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Fan::getUserID, principal.getId());
         queryWrapper.eq(Fan::getOtherID, id);
        boolean remove = fanService.remove(queryWrapper);
       return "redirect:/user/detailToOther/article/"+id;

    }

}
